package com.kizuki.template;


import com.google.common.collect.Lists;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

public class TestTemplate {

    @Test
    public void testWildcard(){
        ArrayList<Student2> student2List = new ArrayList<>();
        student2List.add(new Student2());

        ArrayList<? extends Person> pList = student2List; // 不能再add, 可以get
//        pList.add(new com.kizuki.reflect.Student2()); //三个都不行，不能修改
//        pList.add(new com.kizuki.reflect.Student());
//        pList.add(new com.kizuki.reflect.Person());
        Person person = pList.get(0);


        ArrayList<? super Person> pList2 = new ArrayList<Object>(); // 可以get出object 强转不安全, 可以add
        pList2.add(new Person());
        pList2.add(new Student2());
        pList2.add(new Student());
//        com.kizuki.reflect.Student2 st2 = (com.kizuki.reflect.Student2)pList2.get(0); // 强转报错 get不安全


        ArrayList<?> pList3 = pList2;
        Object o = pList3.get(0); // 只能取出Object
//        pList3.add(new com.kizuki.reflect.Student()); // 不能add


//        如果希望只取出，不插入，就使用? extends Hero
//        如果希望只插入，不取出，就使用? super Hero
//        如果希望，又能插入，又能取出，就不要用通配符？

        ArrayList<Person> personList = new ArrayList<>();
        personList.add(new Student2());

        // 父类泛型能否转换为子类泛型 不能
        // 子类泛型能否转换为父类泛型 不能

        //合并了可以再push吗
    }

    @Test
    public void testCleanTemplate(){
        YouSoHappy u1 = new YouSoHappy();
        YouSoHappy<Object> u2 = new YouSoHappy<>();
        printHappyAble(u1); //编译正常
//      printHappyAble(u2); //编译异常
    }

    public static void printHappyAble(YouSoHappy<Integer> u){
        System.out.println(u);
    }

}


/**
 * 泛型擦除：实现或继承父类的子类，没有指定类型，类似于Object
 */
class ImSoHappy implements HappyAble {
    @Override
    public Object happy(Object t) {
        return null;
    }
}

/**
 * 部分保留
 */
class YouSoHappy<T1> implements HappyAble<T1, Integer> {
    @Override
    public Integer happy(T1 t) {
        return null;
    }

    public static <K> List<K> getList(){
        return Lists.newArrayList();
    }
}

interface HappyAble<T1, T2>{
    T2 happy(T1 t);
}


class Person { }

class Student2 extends Person {

    /**
     * 方法泛型
     * @param t
     * @return <T>
     * @param <T>
     */
    private <T> T getT(T t){
        return t;
    }
}

class Student extends Person { }